/*
 * PassVector.cpp
 *
 *  Created on: Oct 11, 2014
 *      Authors: Avihay Avitan & Stefan Farcas
 */

#include "PassVector.h"

namespace PassVectorSpace {

/**
 * construct an empty PassVector object
 */
PassVector::PassVector ()
{
	logger = Logger::getGSLogger();
	this->startingPassInstance = NULL;
}
/**
 * construct a PassVector object with the starting pass instance AER
 */
PassVector::PassVector (SatelliteAER staringPassInstance)
{
	logger = Logger::getGSLogger();
	addInstance(staringPassInstance);
	updateStartingPassInstance();
}

PassVector::~PassVector ()
{
	// TODO Auto-generated destructor stub
	delete(logger);

}

/**
 * returns the pass start time, if don't have one, returns 0
 */
long PassVector::getPassStartTime()
{
	if (this->startingPassInstance != NULL)
		return this->startingPassInstance->getTimeStamp();
	else
		{
			ProgressStatus status(ProgressStatusType::ERR, "PassVector", "getPassStartTime" , OBJECT_IS_NULL + TIME_RETURN_0 , true, false);
			logger->logError(status);
			return 0;
		}
}

/**
 * returns the instance that is the first to be tracked.
 * if instance not exist - returns 0
 */
long PassVector::getPassStartTrackingTime()
{
	SatelliteAER * aer = aerQueue.getStartTrackingInstance();
	if (aer != NULL)
		return aer->getTimeStamp();
	else
		{
			ProgressStatus status(ProgressStatusType::ERR, "PassVector", "getPassStartTrackingTime" , OBJECT_IS_NULL + TIME_RETURN_0 , true, false);
			logger->logError(status);
			return 0;
		}
}

/**
 * returns the AER queue
 */
SatelliteAERQueue PassVector::getAERQueue()
{
	return aerQueue;
}

/**
 * adding instance to the aerQueue
 * instance - the instance to add
 */
void PassVector::addInstance(SatelliteAER instance)
{
	if (aerQueue.addInstance(instance))
		updateStartingPassInstance();
	else
		{
			ProgressStatus status(ProgressStatusType::ERR, "PassVector", "addInstance" , OBJECT_IS_NULL , true, false);
			logger->logError(status);
		}
}

/**
 *	pops the top instance from the queue and returns it
 */
SatelliteAER *  PassVector::popNextInstance()
{
	SatelliteAER * top = this->aerQueue.popNextInstance();

	if (top == NULL)
	{
		ProgressStatus status(ProgressStatusType::ERR, "PassVector", "popNextInstance" , EMPTY_QUEUE , true, false);
		logger->logError(status);
	}

	updateStartingPassInstance();

	return top;
}

/**
 * returns the top instance in the queue
 */
SatelliteAER * PassVector::getTopInstance()
{
	SatelliteAER * top = aerQueue.getTopInstance();

	if ( top == NULL )
	{
		ProgressStatus status(ProgressStatusType::ERR, "PassVector", "getTopInstance" , EMPTY_QUEUE , true, false);
		logger->logError(status);
	}

	return top;
}

/**
 * update the top instance to the first one that occur after the given timestamp
 * timeStamp - the time which the first instance should be greater than
 */
void PassVector::updateStartingPassInstance(long timeStamp)
{
	SatelliteAER * top = popNextInstance();

	while(top != NULL && top->getTimeStamp()<timeStamp)
	{
		delete(top);
		top = popNextInstance();
	}

	if (top == NULL)
		return;

	addInstance(*top);
	delete(top);
}

/**
 * returns the number of AER instances that the pass has
 */
int PassVector::getCountOfInstances()
{
	return aerQueue.getCountOfInstances();
}

/**
 * returns true if there is at least one AER instance in the queue
 */
bool PassVector::hasNextInstance()
{
	return aerQueue.hasNextInstance();
}

/**
 * set the Access object of the pass
 */
void PassVector::setAccess(Access access)
{
	this->access=access;
}
/**
 * returns the Access object of the class
 */
Access PassVector::getAccess()
{
	return this->access;
}

/**
 * set the satellite is
 */
void PassVector::setSatId(string satId)
{
	this->satId=satId;
}

/**
 * returns the satellite id
 */
string PassVector::getSatId()
{
	return this->satId;
}

/**
 * adding uplink command to the commands queue
 * command - the command to add
 */
bool PassVector::addUplinkCommand(SatelliteUplinkCommand * command)
{

	if (commandsQ.addUplinkCommand(command))
		return true;
	else
	{
		ProgressStatus status(ProgressStatusType::ERR, "PassVector", "addUplinkCommand" , OBJECT_IS_NULL , true, false);
		logger->logError(status);
		return false;
	}
}

/**
 * pop out and returns the next command to satellite
 */
SatelliteUplinkCommand * PassVector::popNextCommand()
{
		SatelliteUplinkCommand * top = this->commandsQ.popNextCommand();

		if (top == NULL)
		{
			ProgressStatus status(ProgressStatusType::ERR, "PassVector", "popNextCommand" , EMPTY_QUEUE , true, false);
			logger->logError(status);
		}

		return top;
}

/**
 * returns the next command to satellite. command not popped!
 */
SatelliteUplinkCommand * PassVector::getTopCommand()
{
	SatelliteUplinkCommand * top = this->commandsQ.getTopCommand();

	if (top == NULL)
	{
		ProgressStatus status(ProgressStatusType::ERR, "PassVector", "getTopCommand" , EMPTY_QUEUE , true, false);
		logger->logError(status);
	}
	return top;
}

/**
 * returns the number of commands in the command queue
 */
int PassVector::getCountOfCommands()
{
	return commandsQ.getCountOfCommands();
}

/**
 * returns true if there is at least one commmand in the command queue
 */
bool PassVector::hasNextCommand()
{
	return commandsQ.hasNextCommand();
}

/**
 * log PassVector details
 */
void PassVector::logPassDetailes()
{
	ProgressStatus status1(ProgressStatusType::INF, "PassVector", "logPassDetailes" , "SatId:" + getSatId() + ", rising sat time:" + getTimeStampOf(getAccess().getStartTime()) + ", end time:" + getTimeStampOf(getAccess().getEndTime()) , true, true);
	logger->logInfo(status1);
	ProgressStatus status2(ProgressStatusType::INF, "PassVector", "logPassDetailes" , "AERs duration(seconds):"  + int2str(getAccess().getDuration()) , true, true);
	logger->logInfo(status2);
	ProgressStatus status3(ProgressStatusType::INF, "PassVector", "logPassDetailes" , "Access interval time:" + int2str(getAccess().getInterval()) + ", number of AERs:" + int2str(getCountOfInstances()) + ", number of commands:" + int2str(getCountOfCommands()) , true, true);
	logger->logInfo(status3);
}

void PassVector::updateStartingPassInstance()
{
	this->startingPassInstance = getTopInstance();
}


} /* namespace PassVector */
